/*
  普通符号
    符号是ES6新增的一个数据类型，他通常使用函数 Symbol(符号名) 来创建

    符号设计的初衷，是为了给对象设置私有属性

    符号具有以下特点：
      没有字面量

      使用 typeof 得到的类型是 symbol

      ！！每次调用 Symbol 函数得到的符号永远不相等，无论符号名是否相同

      符号可以作为对象的属性名存在，这种属性称之为符号属性
        开发者可以通过精心的设计，让这些属性无法通过常规方式被外界访问

        符号属性是不能枚举的，因此在 for-in 循环中无法读取到符号属性，Object.keys方法也无法读取到符号属性

        Object.getOwnPropertyNames 尽管可以得到所有无法枚举的属性，但是仍然无法读取到符号属性

        ES6新增 Object.getOwnPropertySymbols 方法， 可以读取符号
      
      符号无法被隐式转换，因此不能被用于数学运算，字符串拼接或其他隐式转换的场景，但符号可以显示的转换为字符串，
        通过 String 构造函数进行转换即可，console.log 之所以可以输出符号，是他在内部进行了显示转换
*/

const syb1 = Symbol();
const syb2 = Symbol("abc");
console.log(syb1, syb2);

const hero = () => {
  const getRand = Symbol("getRand");
  const test = Symbol("test");
  return {
    attack: 30,
    hp: 300,
    defence: 10,
    [test]: "test",
    gongji() {
      const dmg = this.attack * this[getRand](0.8, 1.1);
      return dmg;
    },

    [getRand](min, max) {
      return Math.random() * (max - min) + min;
    },
  };
};

console.log(hero().gongji());
for (const key in hero()) {
  console.log(key);
}
console.log(
  Object.keys(hero()),
  Object.getOwnPropertyNames(hero()),
  Object.getOwnPropertySymbols(hero())
);

// 使用getOwnPropertySymbols读取属性
const sybs = Object.getOwnPropertySymbols(hero());
console.log("🚀 ~ sybs:", sybs, sybs[1]);
const obj = hero();
console.log(obj[sybs[1]], hero());

// Symbol强制转换为字符串
console.log(String(Symbol("122")));
